/**
 *	@file	pokegear.c
 *	@brief	ポケギアモジュールメイン　常駐
 *	@author	Miyuki Iwasawa
 *	@date	07.06.15
 */

#include "common.h"
#include "system/procsys.h"
#include "system/arc_util.h"
#include "system/arc_tool.h"
#include "system/brightness.h"
#include "system/bmp_list.h"
#include "system/bmp_menu.h"
#include "system/pm_str.h"
#include "system/msgdata.h"
#include "system/fontproc.h"
#include "system/snd_tool.h"
#include "system/clact_util.h"
#include "system/clact_tool.h"
#include "system/render_oam.h"
#include "system/wipe.h"
#include "system/palanm.h"
#include "system/buflen.h"
#include "gflib/touchpanel.h"
#include "field/field_matrix.h"
#include "field/field_place_name.h"
#include "application/app_tool.h"
#include "application/pms_input.h"
#include "system/savedata.h"
#include "gflib/strbuf_family.h"
#include "msgdata/msg.naix"
#include "field/field_se.h"

#include "application/pokegear.h"

#include "pgear_sys.h"
#include "pgear_frm.h"
#include "pgear_act.h"
#include "map/pgear_map.h"
#include "skin/pgear_skin.h"
#include "tel/pgear_tel.h"
#include "radio/pgear_radio.h"

#include "system/pm_overlay.h"
FS_EXTERN_OVERLAY(pgear_frm);

//================================================================
///データ型定義エリア
//================================================================
enum{
 MSEQ_MAININIT,
 MSEQ_SUBINIT,
 MSEQ_FADEIN,
 MSEQ_FADEINWAIT,
 MSEQ_MAIN,
 MSEQ_FADEOUT,
 MSEQ_FADEOUTWAIT,
 MSEQ_PROC_END,
 MSEQ_END,
};

//プロトタイプ宣言　グローバル
//================================================================
///メイン呼び出し

//プロトタイプ宣言　ローカル
//================================================================
///オーバーレイプロセス定義
PROC_RESULT PokeGearProc_Init( PROC *proc,int *seq);
PROC_RESULT PokeGearProc_Main( PROC *proc,int *seq);
PROC_RESULT PokeGearProc_End( PROC *proc,int *seq);

///プロトタイプ　グローバル
void PokeGearVBlank(void* work);

///プロトタイプ　ローカル
static int pgseq_FrameInit(PGEAR_SYS_WORK* wk);
//static int pgseq_FrameMain(PGEAR_SYS_WORK* wk);
static int pgseq_FrameEnd(PGEAR_SYS_WORK* wk);
static int pgseq_MapFrameCall(PGEAR_SYS_WORK* wk);
static int pgseq_MapFrameWait(PGEAR_SYS_WORK* wk);
static int pgseq_WordFrameCall(PGEAR_SYS_WORK* wk);
static int pgseq_WordFrameWait(PGEAR_SYS_WORK* wk);
static int pgseq_SkinFrameCall(PGEAR_SYS_WORK* wk);
static int pgseq_SkinFrameWait(PGEAR_SYS_WORK* wk);
static int pgseq_TelFrameCall(PGEAR_SYS_WORK* wk);
static int pgseq_TelFrameWait(PGEAR_SYS_WORK* wk);
static int pgseq_RadioFrameCall(PGEAR_SYS_WORK* wk);
static int pgseq_RadioFrameWait(PGEAR_SYS_WORK* wk);



/*
///VBlank関連
static void PokeGearVBlank(void * work);
///VRAMバンク定義
static void PokeGearVramBankSet(void);
*/
//----------------------------------------------------------------
///プログラムエリア
//----------------------------------------------------------------

/**
 *	@brief	サブプロセス呼び出し処理
 */
static BOOL PGearSysProcCall(PROC** proc)
{
	if(*proc){
		if(ProcMain(*proc)){
			PROC_Delete(*proc);
			*proc = NULL;
			return TRUE;
		}
	}
	return FALSE;
}

/**
 *	@brief	ポケギア メインプロセス初期化
 *	@param	proc	プロセスデータ
 *	@param	seq		シーケンス
 *
 *	@return	処理状況
 */
PROC_RESULT PokeGearProc_Init( PROC *proc,int *seq)
{
	PGEAR_SYS_WORK *wk = NULL;
	PGEAR_PARAM * param = (PGEAR_PARAM*)PROC_GetParentWork(proc);

	// SE全停止（環境音を止めるため）
	Snd_SeStopAll( 0 );

	//ワークエリア取得
	HeapStatePush();

	//ヒープ作成
	sys_CreateHeap(HEAPID_BASE_APP,HEAPID_POKEGEAR,0x32000);

	wk = PROC_AllocWork( proc,sizeof(PGEAR_SYS_WORK),HEAPID_POKEGEAR);
	memset(wk,0,sizeof(PGEAR_SYS_WORK));

	//パラメータ引継ぎ
	wk->param = param;
	wk->heapID = HEAPID_POKEGEAR;

	//ポケギアセーブデータポインタ取得
	wk->save = wk->param->save;
	wk->pg_save = SaveData_GetPGearSave(wk->param->save);
	wk->ev_save = SaveData_GetEventWork(wk->param->save);
	wk->config_save = SaveData_GetConfig(wk->param->save);
	wk->my_save = SaveData_GetMyStatus(wk->param->save);

	//アプリのオープン状態を取得
	wk->app_open = PGearSv_GetAppOpenFlag(wk->pg_save);

	//現在のキー動作モードを取得
	wk->key_mode = KeyTouchStatus_CheckTouchOrKey((KEYTOUCH_STATUS*)wk->param->pKTStatus);

	//現在のスキン取得
	wk->skin_id = PGearSv_GetSkin(wk->pg_save);

	//初期アプリを決定
	switch(wk->param->mode){
	case PGEAR_CALL_TEL:
		wk->mode = PGAPP_MODE_TEL;
		break;
	case PGEAR_CALL_NORMAL:
	default:
		//セーブデータから現在の選択モードを取得
		wk->mode = PGearSv_GetMode(wk->pg_save);
		if(wk->mode == PGAPP_MODE_MAP){
			if(!(wk->app_open & PGAPP_OPEN_MAP)){
				wk->mode = PGAPP_MODE_SKIN;
			}
		}else if(wk->mode == PGAPP_MODE_RADIO){
			if(!(wk->app_open & PGAPP_OPEN_RADIO)){
				wk->mode = PGAPP_MODE_SKIN;
			}
		}
		break;
	}

	//リターンパラメータ初期化
	wk->ret.valid = 0;
	wk->ret.map.word = PMS_WORD_NULL;
	wk->control = PGCONT_SYS;

	//サウンド引継ぎ設定
	Snd_DataSetByScene( SND_SCENE_SUB_TOWNMAP, 0, 0 );

	return PROC_RES_FINISH;
}

/**
 *	@brief	ポケギア　プロセスメイン
 *	@param	proc	プロセスデータ
 *	@param	seq		シーケンス
 *
 *	@return 処理状況
 */
PROC_RESULT PokeGearProc_Main(PROC* proc,int *seq)
{
	PGEAR_SYS_WORK* wk = PROC_GetWork(proc);

	switch(*seq){
	case PGEAR_SEQ_FRAME_INIT:
		*seq = pgseq_FrameInit(wk);
		break;
	case PGEAR_SEQ_FRAME_END:
		*seq = pgseq_FrameEnd(wk);
		break;
	case PGEAR_SEQ_SKIN_CALL:
		*seq = pgseq_SkinFrameCall(wk);
		break;
	case PGEAR_SEQ_SKIN_WAIT:
		*seq = pgseq_SkinFrameWait(wk);
		break;
	case PGEAR_SEQ_RADIO_CALL:
		*seq = pgseq_RadioFrameCall(wk);
		break;
	case PGEAR_SEQ_RADIO_WAIT:
		*seq = pgseq_RadioFrameWait(wk);
		break;
	case PGEAR_SEQ_MAP_CALL:
		*seq = pgseq_MapFrameCall(wk);
		break;
	case PGEAR_SEQ_MAP_WAIT:
		*seq = pgseq_MapFrameWait(wk);
		break;
	case PGEAR_SEQ_WORD_CALL:
		*seq = pgseq_WordFrameCall(wk);
		break;
	case PGEAR_SEQ_WORD_WAIT:
		*seq = pgseq_WordFrameWait(wk);
		break;
	case PGEAR_SEQ_TEL_CALL:
		*seq = pgseq_TelFrameCall(wk);
		break;
	case PGEAR_SEQ_TEL_WAIT:
		*seq = pgseq_TelFrameWait(wk);
		break;
	case PGEAR_SEQ_END:
		return PROC_RES_FINISH;
	}
	return PROC_RES_CONTINUE;
}

/**
 *	@brief	ポケギア　メインプロセス終了
 *
 *	@param	proc	プロセスデータ
 *	@param	seq		シーケンス
 *
 *	@return 処理状況
 */
PROC_RESULT PokeGearProc_End(PROC* proc,int* seq)
{
	int heapID = 0;
	PGEAR_SYS_WORK* wk = PROC_GetWork(proc);

	//現在の選択モードを書き出し
	PGearSv_SetMode(wk->pg_save,wk->mode);

	//動作モード書き戻し
	KeyTouchStatus_SetTouchOrKey(
		(KEYTOUCH_STATUS*)wk->param->pKTStatus,wk->key_mode);

	//ワークエリア開放
	heapID = wk->heapID;
	PROC_FreeWork(proc);

	// 追加SE領域を開放する
	Snd_SubSceneClear( );

	// 環境音復帰リクエスト発行
	FieldSePlayRequest();

	HeapStatePop();
	HeapStateCheck(heapID);
	sys_DeleteHeap(heapID);

	return PROC_RES_FINISH;
}

/**
 *	@brief	ポケギアVBlank関数
 */
void PokeGearVBlank(void* work)
{
	PGEAR_SYS_WORK* wk = (PGEAR_SYS_WORK*)work;

	/*
		アプリごとの処理実行
	 */
	if(wk->app_vfunc != NULL){
		wk->app_vfunc(wk,wk->app_vwork);
	}

	//パレット転送
	if( wk->palAnm != NULL ){
		PaletteFadeTrans( wk->palAnm );
	}

	//アクター転送
	if(wk->pActSys != NULL){
		if(wk->pSysOam != NULL){
			PGFrame_UpdateTime(wk,FALSE);
			PGSysOam_Draw(wk->pSysOam);
		}
		PGear_ActorMain(wk);
		CATS_RenderOamTrans();
	}
	DoVramTransferManager();
	GF_BGL_VBlankFunc( wk->bgl );
	OS_SetIrqCheckFlag( OS_IE_V_BLANK);
}

/**
 *	@brief	メインフレーム初期化
 */
static int pgseq_FrameInit(PGEAR_SYS_WORK* wk)
{
	if(!PGFrame_FrameInit(wk)){
		return PGEAR_SEQ_FRAME_INIT;
	}
	//呼び出しモードで分岐
	switch(wk->mode){
	case PGAPP_MODE_MAP:
	case PGAPP_MODE_MAP_MARK:
		return PGEAR_SEQ_MAP_CALL;
	case PGAPP_MODE_RADIO:
		return PGEAR_SEQ_RADIO_CALL;
	case PGAPP_MODE_TEL:
		return PGEAR_SEQ_TEL_CALL;
	case PGAPP_MODE_SKIN:
		return PGEAR_SEQ_SKIN_CALL;
	default:
		break;
	}
	return PGEAR_SEQ_SKIN_CALL;
}

/**
 *	@brief	メインフレーム開放
 */
static int pgseq_FrameEnd(PGEAR_SYS_WORK* wk)
{
	if(!PGFrame_FrameRelease(wk)){
		return PGEAR_SEQ_FRAME_END;
	}
	return PGEAR_SEQ_END;
}

/**
 *	@brief	メインフレーム　マップコール
 */
static int pgseq_MapFrameCall(PGEAR_SYS_WORK* wk)
{
	// オーバーレイID宣言
	FS_EXTERN_OVERLAY(pokegear);

	static const PROC_DATA MapProcData = {
		PGearMapProc_Init,
		PGearMapProc_Main,
		PGearMapProc_End,
		FS_OVERLAY_ID(pokegear),
//		NO_OVERLAY_ID,
	};

	wk->proc = PROC_Create(&MapProcData,wk,wk->heapID);
	return PGEAR_SEQ_MAP_WAIT;
}

/**
 *	@brief	メインフレーム　マップウェイト
 */
static int pgseq_MapFrameWait(PGEAR_SYS_WORK* wk)
{
	int next;
	if(!PGearSysProcCall(&wk->proc)){
		return PGEAR_SEQ_MAP_WAIT;
	}

	//マップフレーム終了分岐
	next = wk->next_mode;
	wk->next_mode = 0;
	switch(next){
	case PG_NEXT_MAP:
		wk->mode = PGAPP_MODE_MAP;
		return PGEAR_SEQ_MAP_CALL;
	case PG_NEXT_WORD:
		wk->mode = PGAPP_MODE_MAP_MARK;
		return PGEAR_SEQ_WORD_CALL;
	case PG_NEXT_SKIN:
		wk->mode = PGAPP_MODE_SKIN;
		GF_BGL_VBlankFunc( wk->bgl );
		return PGEAR_SEQ_SKIN_CALL;
	case PG_NEXT_RADIO:
		wk->mode = PGAPP_MODE_RADIO;
		GF_BGL_VBlankFunc( wk->bgl );
		return PGEAR_SEQ_RADIO_CALL;
	case PG_NEXT_TEL:
		wk->mode = PGAPP_MODE_TEL;
		GF_BGL_VBlankFunc( wk->bgl );
		return PGEAR_SEQ_TEL_CALL;
	default:
		break;
	}
	return PGEAR_SEQ_FRAME_END;
}

/**
 *	@brief	メインフレーム　簡易会話コール
 */
static int pgseq_WordFrameCall(PGEAR_SYS_WORK* wk)
{
	if(!PGFrame_FrameRelease(wk)){
		return PGEAR_SEQ_WORD_CALL;
	}

	wk->app_work = PMSI_PARAM_Create( PMSI_MODE_SINGLE,
		PMSI_GUIDANCE_DEFAULT,wk->param->save,(KEYTOUCH_STATUS*)wk->param->pKTStatus, wk->heapID);

	wk->ret.map.word = PMS_WORD_NULL;
	PMSI_PARAM_SetInitializeDataSingle( wk->app_work,wk->ret.map.word);
	{
		FS_EXTERN_OVERLAY(overlay_pmsi);
		static const PROC_DATA PMSProcData = {
			PMSInput_Init,
			PMSInput_Main,
			PMSInput_Quit,
			FS_OVERLAY_ID(overlay_pmsi),
		};
		wk->proc = PROC_Create(&PMSProcData,wk->app_work,wk->heapID);
	}

	return PGEAR_SEQ_WORD_WAIT;
}


/**
 *	@brief	メインフレーム　ワードウェイト
 */
static int pgseq_WordFrameWait(PGEAR_SYS_WORK* wk)
{
	if(!PGearSysProcCall(&wk->proc)){
		return PGEAR_SEQ_WORD_WAIT;
	}

	if(	PMSI_PARAM_CheckCanceled(wk->app_work) == FALSE){
		//変更があれば書き戻し
		wk->ret.map.word = PMSI_PARAM_GetInputDataSingle(wk->app_work);
	}
	PMSI_PARAM_Delete(wk->app_work);

	//マップ側にpushしておいたパラメータを復帰するように通知
	wk->ret.valid = TRUE;
	wk->mode = PGAPP_MODE_MAP_MARK;
	return PGEAR_SEQ_FRAME_INIT;
}

/**
 *	@brief	メインフレーム　スキンコール
 */
static int pgseq_SkinFrameCall(PGEAR_SYS_WORK* wk)
{
	// オーバーレイID宣言
	FS_EXTERN_OVERLAY(pokegear);

	static const PROC_DATA SkinProcData = {
		PGearSkinProc_Init,
		PGearSkinProc_Main,
		PGearSkinProc_End,
		FS_OVERLAY_ID(pokegear),
//		NO_OVERLAY_ID,
	};

	wk->proc = PROC_Create(&SkinProcData,wk,wk->heapID);
	return PGEAR_SEQ_SKIN_WAIT;
}

/**
 *	@brief	メインフレーム　スキンウェイト
 */
static int pgseq_SkinFrameWait(PGEAR_SYS_WORK* wk)
{
	int next;

	if(!PGearSysProcCall(&wk->proc)){
		return PGEAR_SEQ_SKIN_WAIT;
	}

	next = wk->next_mode;
	wk->next_mode = 0;
	//マップフレーム終了分岐
	switch(next){
	case PG_NEXT_MAP:
		wk->mode = PGAPP_MODE_MAP;
		GF_BGL_VBlankFunc( wk->bgl );
		return PGEAR_SEQ_MAP_CALL;
	case PG_NEXT_RADIO:
		wk->mode = PGAPP_MODE_RADIO;
		GF_BGL_VBlankFunc( wk->bgl );
		return PGEAR_SEQ_RADIO_CALL;
	case PG_NEXT_TEL:
		wk->mode = PGAPP_MODE_TEL;
		GF_BGL_VBlankFunc( wk->bgl );
		return PGEAR_SEQ_TEL_CALL;
	default:
		break;
	}
	return PGEAR_SEQ_FRAME_END;
}

/**
 *	@brief	メインフレーム　電話コール
 */
static int pgseq_TelFrameCall(PGEAR_SYS_WORK* wk)
{
	// オーバーレイID宣言
	FS_EXTERN_OVERLAY(pokegear);

	static const PROC_DATA TelProcData = {
		PGearTelProc_Init,
		PGearTelProc_Main,
		PGearTelProc_End,
		FS_OVERLAY_ID(pokegear),
//		NO_OVERLAY_ID,
	};

	wk->proc = PROC_Create(&TelProcData,wk,wk->heapID);
	return PGEAR_SEQ_TEL_WAIT;
}

/**
 *	@brief	メインフレーム　電話ウェイト
 */
static int pgseq_TelFrameWait(PGEAR_SYS_WORK* wk)
{
	int next;

	if(!PGearSysProcCall(&wk->proc)){
		return PGEAR_SEQ_TEL_WAIT;
	}

	next = wk->next_mode;
	wk->next_mode = 0;
	//マップフレーム終了分岐
	switch(next){
	case PG_NEXT_MAP:
		wk->mode = PGAPP_MODE_MAP;
		GF_BGL_VBlankFunc( wk->bgl );
		return PGEAR_SEQ_MAP_CALL;
	case PG_NEXT_SKIN:
		wk->mode = PGAPP_MODE_SKIN;
		GF_BGL_VBlankFunc( wk->bgl );
		return PGEAR_SEQ_SKIN_CALL;
	case PG_NEXT_RADIO:
		wk->mode = PGAPP_MODE_RADIO;
		GF_BGL_VBlankFunc( wk->bgl );
		return PGEAR_SEQ_RADIO_CALL;
	default:
		break;
	}
	return PGEAR_SEQ_FRAME_END;
}

/**
 *	@brief	メインフレーム　ラジオコール
 */
static int pgseq_RadioFrameCall(PGEAR_SYS_WORK* wk)
{
	// オーバーレイID宣言
	FS_EXTERN_OVERLAY(pokegear);

	static const PROC_DATA RadioProcData = {
		PGearRadioProc_Init,
		PGearRadioProc_Main,
		PGearRadioProc_End,
		FS_OVERLAY_ID(pokegear),
//		NO_OVERLAY_ID,
	};

	wk->proc = PROC_Create(&RadioProcData,wk,wk->heapID);
	return PGEAR_SEQ_RADIO_WAIT;
}

/**
 *	@brief	メインフレーム　ラジオウェイト
 */
static int pgseq_RadioFrameWait(PGEAR_SYS_WORK* wk)
{
	int next;

	if(!PGearSysProcCall(&wk->proc)){
		return PGEAR_SEQ_RADIO_WAIT;
	}

	next = wk->next_mode;
	wk->next_mode = 0;
	//マップフレーム終了分岐
	switch(next){
	case PG_NEXT_MAP:
		wk->mode = PGAPP_MODE_MAP;
		GF_BGL_VBlankFunc( wk->bgl );
		return PGEAR_SEQ_MAP_CALL;
	case PG_NEXT_SKIN:
		wk->mode = PGAPP_MODE_SKIN;
		GF_BGL_VBlankFunc( wk->bgl );
		return PGEAR_SEQ_SKIN_CALL;
	case PG_NEXT_TEL:
		wk->mode = PGAPP_MODE_TEL;
		GF_BGL_VBlankFunc( wk->bgl );
		return PGEAR_SEQ_TEL_CALL;
	default:
		break;
	}
	return PGEAR_SEQ_FRAME_END;
}